local U = require "packages/utility/utility"
local ls = require 'packages/lvshisha/utility/lvshi_util'
local DIY = require "packages/diy_utility/diy_utility"

local desc_role = [[
  # 氯师杀身份模式简介
  ___
  此模式基于萌战evolution身份局规则修改
  
  （一）身份改动及身份“明置”相关
  
  1.主公
  
  若游戏人数为6或8，且主公有主公技，游戏开始时，主公可以失去主公技，获得一项“国策”。
  
  国策及其效果分别为：
  
  固略：出牌阶段开始时，你可展示一名角色的身份牌和手牌。回合技(X)，当你成为【杀】的目标后，若你的手牌数不大于手牌上限，你摸一张牌。
  
  尊威：出牌阶段开始时，你明置一张手牌。回合技(X)，其他角色于此轮使用或打出与此牌花色相同的牌时，你可令其弃置一张牌，若为此花色，你获得之。
  
  崇武：出牌阶段开始时，你可摸一张牌，与一名其他角色拼点；若你赢，你于此回合获得效果：回合技(X)，当你使用牌造成伤害时，你可令此伤害+1。
  （X均为主忠方存活角色数）
  
 2.主公身份牌不可被暗置。一名角色的回合开始时，若其身份不为主公，其可明置身份牌，然后触发以下效果：
  
 （1）忠臣
  你弃置场上的一张牌，然后获得“支援”：出牌阶段结束时，你可交给己方角色一张暗置牌并明置。
  
 （2）反贼
  若你为首个明置的角色，你获得一枚先驱标记（回合开始时，你可弃一枚先驱标记，将手牌数补至四张），否则你可令一名手牌数小于你的己方角色摸一张牌。
  
  （3）内奸
  若游戏人数为奇数，内奸的胜利条件改为主公死亡时无反贼存活。
  
  若游戏人数为偶数，内奸明置身份牌后抽取两条命运线并选择一条：
  
  清侧：一名角色的回合结束后，若存活势力数等于轮次数，你将身份变为反贼，摸三张牌。
  
  夺天：其他角色死亡时，若游戏未结束且你杀死过两名角色，你与主公交换身份牌，你增加1点体力上限并回复1点体力，获得其“恩典”，其减少1点体力上限。
  
  拯庙：一名角色的回合结束后，若所有角色的体力值均不相同，且场上有反贼存活，你将身份变为忠臣，存活的忠臣变为内奸。

  申野：一名角色的回合结束后，若所有角色的手牌形成等差数列（公差大于0），则内奸单独胜利。

  3.身份奖惩
  主公击杀忠臣改为获得忠臣的所有牌并失去国策。
  击杀反贼的奖励改为摸X张牌。（X为存活反贼数+1）
]]

local lvshi_role_getLogic = function()
  local lvshi_role_logic = GameLogic:subclass("lvshi_role_logic")
  function lvshi_role_logic:run()
    self.room.settings.enableDeputy = false
    GameLogic.run(self)
  end

  function lvshi_role_logic:initialize(room)
    GameLogic.initialize(self, room)
    self.role_table = {
      nil,
      nil,
      nil,
      nil,
      { "lord", "loyalist", "rebel", "rebel", "renegade" },
      { "lord", "loyalist", "rebel", "rebel", "rebel", "renegade" },
      { "lord", "loyalist", "loyalist", "rebel", "rebel", "rebel", "renegade" },
      { "lord", "loyalist", "loyalist", "rebel", "rebel", "rebel", "rebel", "renegade" },
      { "lord", "loyalist", "loyalist", "loyalist", "rebel", "rebel", "rebel", "rebel", "renegade" },
    }
  end

  function lvshi_role_logic:chooseGenerals()
    local room = self.room ---@class Room
    local generalNum = room.settings.generalNum
    local n = room.settings.enableDeputy and 2 or 1
    local lord = room:getLord()
    local lord_generals = {}
    local lord_num = 3

    if lord ~= nil then
      room:setCurrent(lord)
      local a1 = #room.general_pile
      local a2 = #room.players * generalNum
      if a1 < a2 then
        room:sendLog{
          type = "#NoEnoughGeneralDraw",
          arg = a1,
          arg2 = a2,
          toast = true,
        }
        room:gameOver("")
      end
      lord_num = math.min(a1 - a2, lord_num)
      local generals = table.connect(room:findGenerals(function(g)
        return table.contains(Fk.lords, g)
      end, lord_num), room:getNGenerals(generalNum))
      lord_generals = room:askForGeneral(lord, generals, n)
      local lord_general, deputy
      if type(lord_generals) == "table" then
        deputy = lord_generals[2]
        lord_general = lord_generals[1]
      else
        lord_general = lord_generals
        lord_generals = {lord_general}
      end
      generals = table.filter(generals, function(g)
        return not table.find(lord_generals, function(lg)
          return Fk.generals[lg].trueName == Fk.generals[g].trueName
        end)
      end)
      room:returnToGeneralPile(generals)
      room:prepareGeneral(lord, lord_general, deputy, true)
      room:askForChooseKingdom({lord})
      room:broadcastProperty(lord, "kingdom")

      -- 显示技能
      local canAttachSkill = function(player, skillName)
        local skill = Fk.skills[skillName]
        if not skill then
          fk.qCritical("Skill: "..skillName.." doesn't exist!")
          return false
        end
        if skill.lordSkill and (player.role ~= "lord" or #room.players < 5) then
          return false
        end
        if #skill.attachedKingdom > 0 and not table.contains(skill.attachedKingdom, player.kingdom) then
          return false
        end
        return true
      end

      local lord_skills = {}
      for _, s in ipairs(Fk.generals[lord.general].skills) do
        if canAttachSkill(lord, s.name) then
          table.insertIfNeed(lord_skills, s.name)
        end
      end
      for _, sname in ipairs(Fk.generals[lord.general].other_skills) do
        if canAttachSkill(lord, sname) then
          table.insertIfNeed(lord_skills, sname)
        end
      end

      for _, skill in ipairs(lord_skills) do
        room:doBroadcastNotify("AddSkill", json.encode{
          lord.id,
          skill
        })
      end
    end

    local nonlord = room:getOtherPlayers(lord, true)
    local req = Request:new(nonlord, "AskForGeneral")
    local generals = table.random(room.general_pile, #nonlord * generalNum)
    for i, p in ipairs(nonlord) do
      local arg = table.slice(generals, (i - 1) * generalNum + 1, i * generalNum + 1)
      req:setData(p, { arg, n })
      req:setDefaultReply(p, table.random(arg, n))
    end
    for _, p in ipairs(nonlord) do
      local result = req:getResult(p)
      local general, deputy = result[1], result[2]
      room:findGeneral(general)
      room:findGeneral(deputy)
      room:prepareGeneral(p, general, deputy)
    end
    room:askForChooseKingdom(nonlord)
  end
  return lvshi_role_logic
end

local function areElementsUnique(t)
  if #t < 2 then return false end
  local seen = {}
  for _, v in ipairs(t) do
      if seen[v] then
          return false
      end
      seen[v] = true
  end
  return true
end

local function isArithmeticProgression(t)--GPT
  if #t < 2 then return false end
  table.sort(t)
  local commonDiff = t[2] - t[1]
  for i = 2, #t - 1 do
    if t[i + 1] - t[i] ~= commonDiff then
        return false
    end
  end
  return true
end

local lvshi__destiny = fk.CreateTriggerSkill{
  name = "#lvshi__destiny&",
  priority = 0.01,
  mute = true,
  events = {fk.TurnEnd, fk.Death},
  can_trigger = function(self, event, target, player, data)
    local room = player.room
    if #U.getPrivateMark(player, "destiny") == 0 or player.role ~= "renegade" or not player:hasSkill(self) then return end
    if event == fk.TurnEnd then
      if U.getPrivateMark(player, "destiny")[1] == "lvshi__zhengmiao" then--拯庙
        local hps = table.map(room.alive_players, function (p) return p.hp end)
        return areElementsUnique(hps) and table.find(room.alive_players, function (p) return p.role == "rebel" end)
      elseif U.getPrivateMark(player, "destiny")[1] == "lvshi__qingce" then--清侧
        local kingdoms = {}
        for _, p in ipairs(room.alive_players) do
          table.insertIfNeed(kingdoms, p.kingdom)
        end
        return #kingdoms == room:getTag("RoundCount")
      elseif U.getPrivateMark(player, "destiny")[1] == "lvshi__shenye" then--申野
        return isArithmeticProgression(table.map(room.alive_players, function (p)
          return p:getHandcardNum() end)) and #room.alive_players >= 3
      end
    elseif event == fk.Death then
      if U.getPrivateMark(player, "destiny")[1] == "lvshi__duotian" then
        return player:getMark("evil-count") >= 2
      end
    end
  end,
  on_cost = Util.TrueFunc,
  on_use = function(self, event, target, player, data)
    local room = player.room
    room:setPlayerProperty(player, "role_shown", true)
    room:sendLog{type = "#destinycomplete", from = player.id, arg = U.getPrivateMark(player, "destiny")[1], toast = true}
    if U.getPrivateMark(player, "destiny")[1] == "lvshi__zhengmiao" then
      for _, p in ipairs(room.alive_players) do
        if p.role == "loyalist" then
          room:setPlayerProperty(p, "role", "renegade")
          room:setPlayerProperty(p, "role_shown", true)
        end
      end
      room:setPlayerProperty(player, "role", "loyalist")
    elseif U.getPrivateMark(player, "destiny")[1] == "lvshi__shenye" then
      room:setPlayerMark(player, "@[:]destiny", "lvshi__shenye")
      room:gameOver("renegade")
    elseif U.getPrivateMark(player, "destiny")[1] == "lvshi__qingce" then
      room:setPlayerProperty(player, "role", "rebel")
      player:drawCards(3, "lvshi__qingce")
    elseif U.getPrivateMark(player, "destiny")[1] == "lvshi__duotian" then
      local lord = table.find(room.alive_players, function(p) return p.role == "lord" end)
      room:setPlayerProperty(lord, "role", "renegade")
      room:setPlayerProperty(player, "role", "lord")
      room:changeMaxHp(player, 1)
      room:changeMaxHp(lord, -1)
      room:recover{ who = player, num = 1, skillName = "lvshi__duotian" }
      local lvshi__policy = room:getBanner("@[:]lvshi__policy")
      if lvshi__policy then
        room:handleAddLoseSkills(lord, "-"..lvshi__policy, nil, false)
        room:handleAddLoseSkills(player, lvshi__policy, nil, false)
      end
    end
    local rebels = table.filter(room.alive_players, function (p) return p.role == "renegade" or p.role == "rebel" end)
    if #rebels == 0 then
      room:gameOver("lord+loyalist")
    end
  end,
}

Fk:addSkill(lvshi__destiny)

local lvshi_role_rule = fk.CreateTriggerSkill{
  name = "#lvshi_role_rule",
  priority = 10,
  mute = true,
  events = {fk.GameStart, fk.Death, fk.TurnStart},
  --- FIXME:执行奖惩时机应为fk.BuryVictim，需要SkipGameRule逻辑大改
  can_trigger = function(self, event, target, player, data)
    if event == fk.GameStart then
      return player.role == "lord" and (#player.room.players == 6 or #player.room.players == 8)
    elseif event == fk.Death then
      return target == player and data.damage and data.damage.from and
      ((data.damage.from.role == "lord" and player.role == "loyalist") or data.damage.from.role == "renegade")
    elseif event == fk.TurnStart then
      return target == player and not player.role_shown
    end
  end,
  on_cost = function(self, event, target, player, data)
    if event == fk.TurnStart then
      return player.room:askForSkillInvoke(player, self.name, data, "#ev_show_role")
    else
      return true
    end
  end,
  on_use = function(self, event, target, player, data)
    local room = player.room
    if event == fk.GameStart then
      local lordskills = {}
      for _, s in ipairs(Fk.generals[player.general].skills) do
        if s.lordSkill then
          table.insertIfNeed(lordskills, s.name)
        end
      end
      if #lordskills > 0 and room:askForSkillInvoke(player, "lvshi__policy", nil, "#lvshi__policy-ask") then
        for _, s in ipairs(Fk.generals[player.general].skills) do
          if s.lordSkill then
            room:handleAddLoseSkills(player, "-" .. s.name, nil, false, true)
            room:addTableMark(player, MarkEnum.InvalidSkills, s.name)
          end
        end
        local lvshi__policy = room:askForChoice(player, {"lvshi__gulve&", "lvshi__zunwei&", "lvshi__shenwu&"}, "lvshi__policy", "#lvshi__policy-get", true)
        ls.choicelog(player, lvshi__policy)
        room:setBanner("@[:]lvshi__policy", lvshi__policy)
        room:handleAddLoseSkills(player, lvshi__policy, nil, false)
      end
    elseif event == fk.Death then
      if data.damage.from.role == "lord" then
        local cards_id = player:getCardIds("he")
        room:obtainCard(data.damage.from.id, cards_id, false, fk.ReasonPrey)
      elseif data.damage.from.role == "renegade" then
        room:addPlayerMark(data.damage.from, "evil-count")
      end
    elseif event == fk.TurnStart then
      room:setPlayerProperty(player, "role_shown", true)
      room:broadcastProperty(player, "role")
      room.logic:trigger("fk.RoleShown", player, {from = player.id})
      if player.role == "loyalist" then
        room:handleAddLoseSkills(player, "lvshi__zhiyuan")
        local targets = table.filter(room.alive_players, function (p) return #p:getCardIds("ej") > 0 end)
        if #targets == 0 then return end
        local from = room:askForChoosePlayers(player, table.map(targets, Util.IdMapper), 1, 1,
        "#ev_shenguan-choose", self.name, true)
        if #from > 0 then
          from = room:getPlayerById(from[1])
          local cid = room:askForCardChosen(player, from, "ej", self.name)
          if cid then
            room:moveCardTo(cid, Card.DiscardPile, nil, fk.ReasonDiscard, self.name, "", true)
          end
        end
      elseif player.role == "rebel" then
        if not room:getTag("prophet") or room:getTag("prophet") == "" then
          room:setTag("prophet", player.id)
          room:addPlayerMark(player, "@!prophet")
          player:addFakeSkill("prophet_skill&")
          player:prelightSkill("prophet_skill&", true)
        else
          local targets = table.map(table.filter(room.alive_players,
          function(p) return p:getHandcardNum() < player:getHandcardNum() and p.role_shown and p.role == "rebel" end), Util.IdMapper)
          local to = room:askForChoosePlayers(player, targets, 1, 1, "#knight-choose", self.name, true)
          if #to > 0 then
            room:getPlayerById(to[1]):drawCards(1, self.name)
          end
        end
      elseif player.role == "renegade" and #room.players % 2 == 0 then
        local destiny = room:getTag("destiny")
        if not destiny or destiny == "" then destiny = {"lvshi__qingce", "lvshi__duotian", "lvshi__zhengmiao", "lvshi__shenye"} end
        local choice = room:askForChoice(player, table.random(destiny, 2), "destiny", "#destiny-get", true)
        U.setPrivateMark(player, "destiny", {choice})
        table.removeOne(destiny, choice)
        room:setTag("destiny", destiny)
        room:handleAddLoseSkills(player, "#lvshi__destiny&", self.name, false)
      end
    end
  end,
}

Fk:addSkill(lvshi_role_rule)

local prophet_skill = fk.CreateTriggerSkill{
  name = "prophet_skill&",
  anim_type = "drawcard",
  events = {fk.TurnStart},
  can_trigger = function(self, event, target, player, data)
    return player:hasSkill(self) and target == player and player:getHandcardNum() < 4
  end,
  on_use = function(self, event, target, player, data)
    player.room:removePlayerMark(player, "@!prophet")
    if player:getMark("@!prophet") == 0 then
      player:loseFakeSkill("prophet_skill&")
      -- room:handleAddLoseSkills(player, "-vanguard_skill&", nil, false, true)
    end
    local num = 4 - player:getHandcardNum()
    if num > 0 then
      player:drawCards(num, self.name)
    end
  end,
}
Fk:addSkill(prophet_skill)
Fk:loadTranslationTable{
  ["prophet_skill&"] = "先驱",
  [":prophet_skill&"] = "回合开始时，你可弃一枚“先驱”，将手牌摸至4张。",
  ["prophet"] = "先驱",
}

local ev_ruizhi = fk.CreateTriggerSkill{
  name = "lvshi__gulve&",
  anim_type = "defensive",
  events = {fk.TargetConfirmed, fk.EventPhaseStart},
  can_trigger = function(self, event, target, player, data)
    if event == fk.TargetConfirmed then
      if target == player and player:hasSkill(self) and data.firstTarget and data.card.trueName == "slash"
      and player:getHandcardNum() <= player:getMaxCards() then
        local n = #table.filter(player.room.alive_players, function (p) return p.role == "lord" or p.role == "loyalist" end)
        return player:getMark("lvshi__gulve-turn") < n
      end
    elseif event == fk.EventPhaseStart then
      return player:hasSkill(self) and target == player and player.phase == Player.Play
    end
  end,
  on_cost = function(self, event, target, player, data)
    if event == fk.TargetConfirmed then
      return player.room:askForSkillInvoke(player, self.name)
    elseif event == fk.EventPhaseStart then
      local targets = table.map(table.filter(player.room:getOtherPlayers(player), function(p) return not p.role_shown end), Util.IdMapper)
      local to = player.room:askForChoosePlayers(player, targets, 1, 1, "#lvshi__gulve-target", self.name, true)
      if #to > 0 then
        self.cost_data = to[1]
        player.room:doIndicate(player.id, {to[1]})
        return true
      end
    end
  end,
  on_use = function(self, event, target, player, data)
    local room = player.room
    if event == fk.TargetConfirmed then
      player.room:addPlayerMark(player, "lvshi__gulve-turn")
      player:drawCards(1, self.name)
    elseif event == fk.EventPhaseStart then
      local to = room:getPlayerById(self.cost_data)
      room:setPlayerProperty(to, "role_shown", true)
      room:broadcastProperty(to, "role")
      to:showCards(to:getCardIds("h"))
    end
  end,
}

Fk:addSkill(ev_ruizhi)

local ev_shenwu = fk.CreateTriggerSkill{
  name = "lvshi__shenwu&",
  anim_type = "offensive",
  events = {fk.EventPhaseStart, fk.DamageCaused},
  can_trigger = function(self, event, target, player, data)
    if event == fk.EventPhaseStart then
      return target == player and player:hasSkill(self) and player.phase == Player.Play
    elseif event == fk.DamageCaused then
      return target == player and player:getMark("@ev_shenwu-turn") > 0 and data.card
    end
  end,
  on_use = function(self, event, target, player, data)
    local room = player.room
    if event == fk.EventPhaseStart then
      player:drawCards(1, self.name)
      local to = room:askForChoosePlayers(player, table.map(table.filter(room:getOtherPlayers(player), function(p)
        return player:canPindian(p) end), Util.IdMapper),
        1, 1, "#lvshi__shenwu-choose", self.name, false)
      if #to > 0 then
        local pindian = player:pindian(table.map(to, Util.Id2PlayerMapper), self.name)
        if pindian.results[to[1]].winner == player then
          local n = #table.filter(room.alive_players, function (p) return p.role == "lord" or p.role == "loyalist" end)
          room:setPlayerMark(player, "@ev_shenwu-turn", n)
        end
      end
    elseif event == fk.DamageCaused then
      room:removePlayerMark(player, "@ev_shenwu-turn")
      data.damage = data.damage + 1
    end
  end,
}

Fk:addSkill(ev_shenwu)

local lvshi__zunwei = fk.CreateTriggerSkill{
  name = "lvshi__zunwei&",
  anim_type = "control",
  events = {fk.EventPhaseStart, fk.CardUsing, fk.CardResponding},
  can_trigger = function(self, event, target, player, data)
    if event == fk.EventPhaseStart then
      return target == player and player:hasSkill(self) and player.phase == Player.Play and not player:isKongcheng()
    elseif event == fk.CardUsing or event == fk.CardResponding then
      if player:hasSkill(self) and target ~= player and #player:getTableMark("@lvshi__zunwei-round") > 0 then
        local n = #table.filter(player.room.alive_players, function (p) return p.role == "lord" or p.role == "loyalist" end)
        return player:getMark("lvshi__zunwei-turn") < n and
        data.card:getSuitString(true) == player:getTableMark("@lvshi__zunwei-round")[1] and not target:isNude()
      end
    end
  end,
  on_cost = function(self, event, target, player, data)
    if event == fk.EventPhaseStart then
      local card = player.room:askForCard(player, 1, 1, false, self.name, false, ".", "#lvshi__zunwei-show")
      if #card > 0 then
        self.cost_data = card
        return true
      end
    elseif event == fk.CardUsing or event == fk.CardResponding then
      return player.room:askForSkillInvoke(player, self.name, nil, "#lvshi__zunwei-invoke::"..target.id)
    end
  end,
  on_use = function(self, event, target, player, data)
    local room = player.room
    if event == fk.EventPhaseStart then
      player:showCards(self.cost_data)
      room:setPlayerMark(player, "@lvshi__zunwei-round", {Fk:getCardById(self.cost_data[1]):getSuitString(true)})
    elseif event == fk.CardUsing or event == fk.CardResponding then
      room:addPlayerMark(player, "lvshi__zunwei-turn")
      local card = room:askForDiscard(target, 1, 1, true, self.name, false)
      --local card = room:askForCard(target, 1, 1, false, self.name, false, ".", "#lvshi__zunwei-give:"..player.id)
      if #card > 0 and Fk:getCardById(card[1]):getSuitString(true) == player:getTableMark("@lvshi__zunwei-round")[1] then
        room:obtainCard(player.id, card[1], false, fk.ReasonJustMove)
      end
      --room:obtainCard(player.id, card[1], false, fk.ReasonGive)
    end
  end,
}

Fk:addSkill(lvshi__zunwei)

local lvshi__zhiyuan = fk.CreateTriggerSkill{
  name = "lvshi__zhiyuan",
  events = {fk.EventPhaseEnd},
  can_trigger = function(self, event, target, player, data)
    return player.phase == Player.Play and target == player and player:hasSkill(self) and not player:isKongcheng()
  end,
  on_cost = function(self, event, target, player, data)
    local targets = table.map(table.filter(player.room:getOtherPlayers(player), function(p)
      return ls.isFriend(player, p) end), Util.IdMapper)
    local cards = ls.gethidecards(player)
    local tar, id = player.room:askForChooseCardAndPlayers(player, targets, 1, 1, tostring(Exppattern{ id = cards }), "#lvshi__zhiyuan", self.name, true)
    if #tar > 0 and id then
      self.cost_data = {tar, id}
      return true
    end
  end,
  on_use = function(self, event, target, player, data)
    local room = player.room
    local tar = self.cost_data[1]
    local id = self.cost_data[2]
    if #tar > 0 and id then
      room:moveCardTo(id, Card.PlayerHand, room:getPlayerById(tar[1]), fk.ReasonGive, self.name, nil, false, player.id)
      DIY.ShowCards(room:getPlayerById(tar[1]), id)
    end
  end
}

Fk:addSkill(lvshi__zhiyuan)

local role_mode = fk.CreateGameMode{
  name = "lvshi_role_mode", -- just to let it at the top of list
  minPlayer = 5,
  maxPlayer = 8,
  main_mode = "role_mode",
  rule = lvshi_role_rule,
  logic = lvshi_role_getLogic,
  surrender_func = Fk.game_modes["aaa_role_mode"].surrenderFunc,
  reward_punish = function (self, victim, killer)
    if not killer or killer.dead then return end
    local room = killer.room
    if victim.role == "rebel" then
      local n = #table.filter(room.alive_players, function (p) return p.role == "rebel" end) + 1
      killer:drawCards(n, "kill")
    end
    if killer.role == "lord" and victim.role == "loyalist" then
      local lvshi__policy = room:getBanner("@[:]lvshi__policy")
      if lvshi__policy then
        room:handleAddLoseSkills(killer, "-"..lvshi__policy, nil, false)      
      end
    end
  end,
  winner_getter = function(self, victim)
    local room = victim.room
    if not victim.surrendered and victim.rest > 0 then
      return ""
    end
    local winner = ""
    local alive = table.filter(room.players, function(p)
      return not p.surrendered and not (p.dead and p.rest == 0)
    end)
    --local destiny = table.find(room.alive_players, function (p) return p:getMark("@[:]destiny") == "lvshi__cunzuo" end)
    local destiny = room:getBanner("@[:]lvshi__destiny") and room:getBanner("@[:]lvshi__destiny") == "success"
    if victim.role == "lord" then
      if (#alive == 1 and alive[1].role == "renegade") or ((#room.players == 5 or #room.players == 7 or #room.players == 9)
      and not table.find(room.alive_players, function (p) return p.role == "rebel" end)) then
        winner = "renegade"
      else
        if destiny then
          winner = "rebel+renegade"
        else
          winner = "rebel"
        end
      end
    elseif victim.role ~= "loyalist" then
      local lord_win = true
      for _, p in ipairs(alive) do
        if p.role == "rebel" or p.role == "renegade" then
          lord_win = false
          break
        end
      end
      if lord_win then
        if destiny then
          winner = "lord+loyalist+renegade"
        else
          winner = "lord+loyalist"
        end
      end
    end
    return winner
  end,
}


Fk:loadTranslationTable{
  ["lvshi_role_mode"] = "氯师身份模式",
  [":lvshi_role_mode"] = desc_role,
  ["#lvshi_role_rule"] = "身份规则",
  ["@[:]lvshi__policy"] = "国策",
  ["lvshi__policy"] = "国策",
  ["#lvshi__policy-ask"] = "你可以用一项国策替换主公技",
  ["#lvshi__policy-get"] = "请选择一项国策获得之",
  ["#ev_show_role"] = "你可以明置身份牌",
  ["#ev_shenguan-choose"] = "你可以弃置场上一张牌",
  ["#knight-choose"] = "你可令一名手牌数小于你的队友摸一张牌",
  ["@@prophet"] = "先知",
  ["destiny"] = "天命",
  ["#destiny-get"] = "请选择你的天命",

  ["rebel+renegade"] = "反贼，内奸",
  ["lord+loyalist+renegade"] = "主公，忠臣，内奸",

  ["lvshi__gulve&"] = "固略",
  [":lvshi__gulve&"] = "出牌阶段开始时，你可展示一名角色的身份牌和手牌。回合技（X），当你成为【杀】的目标后，若你的手牌数不大于手牌上限，你摸一张牌。（X为主忠方存活角色数）",
  ["#lvshi__gulve-target"] = "固略：你可展示一名角色的身份牌和手牌",

  ["lvshi__zunwei&"] = "尊威",
  [":lvshi__zunwei&"] = "出牌阶段开始时，你展示一张手牌。回合技（X），其他角色于此轮使用或打出与此牌花色相同的牌时，你可令其弃置一张牌，若为此花色，你获得之。（X为主忠方存活角色数）",
  ["@lvshi__zunwei-round"] = "<b><font color=\"#FFD700\">尊威</font></b>",
  ["#lvshi__zunwei-invoke"] = "尊威：你可以令%dest弃置一张牌",
  ["#lvshi__zunwei-show"] = "尊威：请展示一张手牌",
  ["#lvshi__zunwei-give"] = "尊威：请交给%src一张牌",
  
  ["lvshi__shenwu&"] = "崇武",
  [":lvshi__shenwu&"] = "出牌阶段开始时，你可摸一张牌，与一名其他角色拼点；若你赢，你于此回合获得效果：回合技（X），当你使用牌造成伤害时，你可令此伤害+1。（X为主忠方存活角色数）",
  ["#lvshi__shenwu-choose"] = "请选择一名角色拼点",
  ["@ev_shenwu-turn"] = "崇武",

  ["lvshi__zhiyuan"] = "支援",
  [":lvshi__zhiyuan"] = "出牌阶段结束时，你可交给一名己方角色一张暗置手牌并明置。",
  ["#lvshi__zhiyuan"] = "你可交给一名己方角色一张暗置手牌",
  [":@lvshi__zhiyuan"] = "将牌交给一名己方角色并明置",

  ["@[private]destiny"] = "天命",

  ["lvshi__qingce"] = "清侧",
  [":lvshi__qingce"] = "一名角色的回合结束后，若存活势力数等于轮次数，你将身份变为反贼，摸三张牌。",
  ["lvshi__duotian"] = "夺天",
  [":lvshi__duotian"] = "其他角色死亡时，若你杀死过两名角色，你与主公交换身份牌，你增加1点体力上限并回复1点体力，获得其“恩典”，其减少1点体力上限。",
  ["lvshi__zhengmiao"] = "拯庙",
  [":lvshi__zhengmiao"] = "一名角色的回合结束后，若所有角色的体力值均不相同，且场上有反贼存活，你将身份变为忠臣，存活的忠臣变为内奸。",
  ["lvshi__shenye"] = "申野",
  [":lvshi__shenye"] = "一名角色的回合结束后，若所有角色的手牌形成等差数列，则内奸单独胜利。",
  ["@[:]destiny"] = "完成天命",

  ["#destinycomplete"] = "%from 已完成天命 %arg",
}

return role_mode
 